#pragma once

#include "znx_defs.h"
#include <stdatomic.h>

typedef _Atomic(int64_t)             znx_atomic_int64_t;
typedef _Atomic(int64_t)             znx_atomic_bool_t;
typedef _Atomic(intptr_t)            znx_atomic_ptr_t;

////////////////////////////// atomic int //////////////////////////////

static inline void
znx_atomic_int64_reset(znx_atomic_int64_t *m)
{
    *m = 0;
}

static inline int64_t
znx_atomic_int64_swap(znx_atomic_int64_t *m, int64_t v)
{
    return atomic_exchange(m, v);
}

static inline znx_bool_t
znx_atomic_int64_cas(znx_atomic_int64_t *m, int64_t prev, int64_t next)
{
    return atomic_compare_exchange_strong(m, &prev, next);
}

static inline int64_t
znx_atomic_int64_fetch_add(znx_atomic_int64_t *m, int64_t v)
{
    return atomic_fetch_add(m, v);
}

static inline int64_t
znx_atomic_int64_add_fetch(znx_atomic_int64_t *m, int64_t v)
{
    return atomic_fetch_add(m, v) + v;
}

static inline int64_t
znx_atomic_int64_load(znx_atomic_int64_t *m)
{
    return atomic_load(m);
}

////////////////////////////// atomic bool //////////////////////////////

static inline void
znx_atomic_bool_reset(znx_atomic_bool_t *m)
{
    *m = 0;
}

static inline void
znx_atomic_bool_set_true(znx_atomic_bool_t *m)
{
    atomic_store(m, 1);
}

static inline void
znx_atomic_bool_set_false(znx_atomic_bool_t *m)
{
    atomic_store(m, 0);
}

static inline znx_bool_t
znx_atomic_bool_is_true(znx_atomic_bool_t *m)
{
    return (atomic_load(m) == 1);
}

////////////////////////////// atomic ptr //////////////////////////////

static inline void
znx_atomic_ptr_reset(znx_atomic_ptr_t *m)
{
    *m = 0;
}

static inline void *
znx_atomic_ptr_swap(znx_atomic_ptr_t *m, void *v)
{
    return (void *)atomic_exchange(m, (intptr_t)v);
}

static inline znx_bool_t
znx_atomic_ptr_cas(znx_atomic_ptr_t *m, void *prev, void *next)
{
    return atomic_compare_exchange_strong(m, (intptr_t *)&prev, (intptr_t)next);
}

static inline void *
znx_atomic_ptr_load(znx_atomic_ptr_t *m)
{
    return (void *)atomic_load(m);
}
